home *** CD-ROM | disk | FTP | other *** search
/ Game Programming - All in One (3rd Edition) / game_prog_all_in_one_3rd_ed.iso / DirectX / DX8 Fix / d3dx8_0b.exe / mload.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-14  |  45.4 KB  |  1,549 lines

  1. //-----------------------------------------------------------------------------
  2. // File: mload.cpp
  3. //
  4. // Copyright (c) 1999-2001 Microsoft Corporation. All rights reserved.
  5. //-----------------------------------------------------------------------------
  6.  
  7. #include <windows.h>
  8. #include <mmsystem.h>
  9. #include <objbase.h>
  10. #include <malloc.h> // _alloca
  11. #include <stdio.h>
  12. #include <d3d8.h>
  13. #include <d3dx8.h>
  14. #include "resource.h"
  15. #include "D3DApp.h"
  16. #include "D3DFont.h"
  17. #include "D3DUtil.h"
  18. #include "DXUtil.h"
  19. #include "D3DRes.h"
  20. #include "rmxfguid.h"
  21. #include "rmxftmpl.h"
  22. #include "dxutil.h"
  23. #include "SkinnedMesh.h"
  24.  
  25.  
  26. HRESULT CalculateSum(SFrame *pframe, D3DXMATRIX *pmatCur, D3DXVECTOR3 *pvCenter, 
  27.                      UINT *pcVertices)
  28. {
  29.     HRESULT hr = S_OK;
  30.     PBYTE pbPoints = NULL;
  31.     UINT cVerticesLocal = 0;
  32.     PBYTE pbCur;
  33.     D3DXVECTOR3 *pvCur;
  34.     D3DXVECTOR3 vTransformedCur;
  35.     UINT iPoint;
  36.     SMeshContainer *pmcCur;
  37.     SFrame *pframeCur;
  38.     UINT cVertices;
  39.     D3DXMATRIX matLocal;
  40.     
  41.     D3DXMatrixMultiply(&matLocal, &pframe->matRot, pmatCur);
  42.     
  43.     pmcCur = pframe->pmcMesh;
  44.     while (pmcCur != NULL)
  45.     {
  46.         DWORD fvfsize = D3DXGetFVFVertexSize(pmcCur->pMesh->GetFVF());
  47.         
  48.         cVertices = pmcCur->pMesh->GetNumVertices();
  49.         
  50.         hr = pmcCur->pMesh->LockVertexBuffer(0, &pbPoints);
  51.         if (FAILED(hr))
  52.             goto e_Exit;
  53.         
  54.         for( iPoint=0, pbCur = pbPoints; iPoint < cVertices; iPoint++, pbCur += fvfsize)
  55.         {
  56.             pvCur = (D3DXVECTOR3*)pbCur;
  57.             
  58.             if ((pvCur->x != 0.0) || (pvCur->y != 0.0) || (pvCur->z != 0.0))
  59.             {
  60.                 cVerticesLocal++;
  61.                 
  62.                 D3DXVec3TransformCoord(&vTransformedCur, pvCur, &matLocal);
  63.                 
  64.                 pvCenter->x += vTransformedCur.x;
  65.                 pvCenter->y += vTransformedCur.y;
  66.                 pvCenter->z += vTransformedCur.z;
  67.             }
  68.         }
  69.         
  70.         
  71.         pmcCur->pMesh->UnlockVertexBuffer();
  72.         pbPoints = NULL;
  73.         
  74.         pmcCur = pmcCur->pmcNext;
  75.     }
  76.     
  77.     *pcVertices += cVerticesLocal;
  78.     
  79.     pframeCur = pframe->pframeFirstChild;
  80.     while (pframeCur != NULL)
  81.     {
  82.         hr = CalculateSum(pframeCur, &matLocal, pvCenter, pcVertices);
  83.         if (FAILED(hr))
  84.             goto e_Exit;
  85.         
  86.         pframeCur = pframeCur->pframeSibling;
  87.     }
  88.     
  89. e_Exit:
  90.     if (pbPoints != NULL)
  91.     {
  92.         pmcCur->pMesh->UnlockVertexBuffer();
  93.     }
  94.     
  95.     return hr;
  96. }
  97.  
  98.  
  99.  
  100.  
  101. HRESULT CalculateRadius(SFrame *pframe, D3DXMATRIX *pmatCur, D3DXVECTOR3 *pvCenter, 
  102.                         float *pfRadiusSq)
  103. {
  104.     HRESULT hr = S_OK;
  105.     PBYTE pbPoints = NULL;
  106.     PBYTE pbCur;
  107.     D3DXVECTOR3 *pvCur;
  108.     D3DXVECTOR3 vDist;;
  109.     UINT iPoint;
  110.     UINT cVertices;
  111.     SMeshContainer *pmcCur;
  112.     SFrame *pframeCur;
  113.     float fRadiusLocalSq;
  114.     float fDistSq;
  115.     D3DXMATRIX matLocal;
  116.     
  117.     D3DXMatrixMultiply(&matLocal, &pframe->matRot, pmatCur);
  118.     
  119.     pmcCur = pframe->pmcMesh;
  120.     fRadiusLocalSq = *pfRadiusSq;
  121.     while (pmcCur != NULL)
  122.     {
  123.         DWORD fvfsize = D3DXGetFVFVertexSize(pmcCur->pMesh->GetFVF());
  124.         
  125.         cVertices = pmcCur->pMesh->GetNumVertices();
  126.         
  127.         hr = pmcCur->pMesh->LockVertexBuffer(0, &pbPoints);
  128.         if (FAILED(hr))
  129.             goto e_Exit;
  130.         
  131.         for( iPoint=0, pbCur = pbPoints; iPoint < cVertices; iPoint++, pbCur += fvfsize )
  132.         {
  133.             pvCur = (D3DXVECTOR3*)pbCur;
  134.             
  135.             if ((pvCur->x == 0.0) && (pvCur->y == 0.0) && (pvCur->z == 0.0))
  136.                 continue;
  137.             
  138.             D3DXVec3TransformCoord(&vDist, pvCur, &matLocal);
  139.             
  140.             vDist -= *pvCenter;
  141.             
  142.             fDistSq = D3DXVec3LengthSq(&vDist);
  143.             
  144.             if( fDistSq > fRadiusLocalSq )
  145.                 fRadiusLocalSq = fDistSq;
  146.         }
  147.         
  148.         
  149.         pmcCur->pMesh->UnlockVertexBuffer();
  150.         pbPoints = NULL;
  151.         
  152.         pmcCur = pmcCur->pmcNext;
  153.     }
  154.     
  155.     *pfRadiusSq = fRadiusLocalSq;
  156.     
  157.     pframeCur = pframe->pframeFirstChild;
  158.     while (pframeCur != NULL)
  159.     {
  160.         hr = CalculateRadius(pframeCur, &matLocal, pvCenter, pfRadiusSq);
  161.         if (FAILED(hr))
  162.             goto e_Exit;
  163.         
  164.         pframeCur = pframeCur->pframeSibling;
  165.     }
  166.     
  167. e_Exit:
  168.     if (pbPoints != NULL)
  169.     {
  170.         pmcCur->pMesh->UnlockVertexBuffer();
  171.     }
  172.     
  173.     return hr;
  174. }
  175.  
  176.  
  177.  
  178.  
  179. HRESULT CalculateBoundingSphere(SDrawElement *pdeCur)
  180. {
  181.     HRESULT hr = S_OK;
  182.     D3DXVECTOR3 vCenter(0,0,0);
  183.     UINT cVertices = 0;
  184.     float fRadiusSq = 0;
  185.     D3DXMATRIX matCur;
  186.     
  187.     D3DXMatrixIdentity(&matCur);
  188.     hr = CalculateSum(pdeCur->pframeRoot, &matCur, &vCenter, &cVertices);
  189.     if (FAILED(hr))
  190.         goto e_Exit;
  191.     
  192.     if (cVertices > 0)
  193.     {
  194.         vCenter /= (float)cVertices;
  195.         
  196.         D3DXMatrixIdentity(&matCur);
  197.         hr = CalculateRadius(pdeCur->pframeRoot, &matCur, &vCenter, &fRadiusSq);
  198.         if (FAILED(hr))
  199.             goto e_Exit;
  200.     }
  201.     
  202.     pdeCur->fRadius = (float)sqrt((double)fRadiusSq);;
  203.     pdeCur->vCenter = vCenter;
  204. e_Exit:
  205.     return hr;
  206. }
  207.  
  208.  
  209.  
  210.  
  211. HRESULT CMyD3DApplication::FindBones(SFrame *pframeCur, SDrawElement *pde)
  212. {
  213.     HRESULT hr = S_OK;
  214.     SMeshContainer *pmcMesh;
  215.     SFrame *pframeChild;
  216.     
  217.     pmcMesh = pframeCur->pmcMesh;
  218.     while (pmcMesh != NULL)
  219.     {
  220.         if (pmcMesh->m_pSkinMesh)
  221.         {
  222.             char** pBoneName = static_cast<char**>(pmcMesh->m_pBoneNamesBuf->GetBufferPointer());
  223.             for (DWORD i = 0; i < pmcMesh->m_pSkinMesh->GetNumBones(); ++i)
  224.             {
  225.                 SFrame* pFrame = pde->FindFrame(pBoneName[i]);
  226.                 pmcMesh->m_pBoneMatrix[i] = &(pFrame->matCombined);
  227.             }
  228.         }
  229.         pmcMesh = pmcMesh->pmcNext;
  230.     }
  231.     
  232.     pframeChild = pframeCur->pframeFirstChild;
  233.     while (pframeChild != NULL)
  234.     {
  235.         hr = FindBones(pframeChild, pde);
  236.         if (FAILED(hr))
  237.             return hr;
  238.         
  239.         pframeChild = pframeChild->pframeSibling;
  240.     }
  241.     
  242.     return S_OK;
  243. }
  244.  
  245.  
  246.  
  247.  
  248. HRESULT CMyD3DApplication::LoadMeshHierarchy()
  249. {
  250.     TCHAR* pszFile = m_szPath;
  251.     SDrawElement *pdeMesh = NULL;
  252.     HRESULT hr = S_OK;
  253.     LPDIRECTXFILE pxofapi = NULL;
  254.     LPDIRECTXFILEENUMOBJECT pxofenum = NULL;
  255.     LPDIRECTXFILEDATA pxofobjCur = NULL;
  256.     DWORD dwOptions;
  257.     int cchFileName;
  258.  
  259.     if (pszFile == NULL)
  260.         return E_INVALIDARG;
  261.     
  262.     pdeMesh = new SDrawElement();
  263.     
  264.     delete pdeMesh->pframeRoot;
  265.     pdeMesh->pframeAnimHead = NULL;
  266.     
  267.     pdeMesh->pframeRoot = new SFrame();
  268.     if (pdeMesh->pframeRoot == NULL)
  269.     {
  270.         hr = E_OUTOFMEMORY;
  271.         goto e_Exit;
  272.     }
  273.     
  274.     
  275.     dwOptions = 0;
  276.     
  277.     cchFileName = strlen(pszFile);
  278.     if (cchFileName < 2)
  279.     {
  280.         hr = E_FAIL;
  281.         goto e_Exit;
  282.     }
  283.     
  284.     hr = DirectXFileCreate(&pxofapi);
  285.     if (FAILED(hr))
  286.         goto e_Exit;
  287.     
  288.     // Register templates for d3drm.
  289.     hr = pxofapi->RegisterTemplates((LPVOID)D3DRM_XTEMPLATES,
  290.         D3DRM_XTEMPLATE_BYTES);
  291.     if (FAILED(hr))
  292.         goto e_Exit;
  293.     
  294.     // Create enum object.
  295.     hr = pxofapi->CreateEnumObject((LPVOID)pszFile,
  296.         DXFILELOAD_FROMFILE,
  297.         &pxofenum);
  298.     if (FAILED(hr))
  299.         goto e_Exit;
  300.     
  301.     
  302.     // Enumerate top level objects.
  303.     // Top level objects are always data object.
  304.     while (SUCCEEDED(pxofenum->GetNextDataObject(&pxofobjCur)))
  305.     {
  306.         hr = LoadFrames(pxofobjCur, pdeMesh, dwOptions, m_dwFVF,
  307.             m_pd3dDevice,
  308.             pdeMesh->pframeRoot);
  309.         GXRELEASE(pxofobjCur);
  310.         
  311.         if (FAILED(hr))
  312.             goto e_Exit;
  313.     }
  314.     
  315.     hr = FindBones(pdeMesh->pframeRoot, pdeMesh);
  316.     if (FAILED(hr))
  317.         goto e_Exit;
  318.     
  319.     
  320.     delete []pdeMesh->szName;
  321.     pdeMesh->szName = new char[cchFileName+1];
  322.     if (pdeMesh->szName == NULL)
  323.     {
  324.         hr = E_OUTOFMEMORY;
  325.         goto e_Exit;
  326.     }
  327.     memcpy(pdeMesh->szName, pszFile, cchFileName+1);
  328.  
  329.     // delete the current mesh, now that the load has succeeded
  330.     DeleteSelectedMesh();
  331.  
  332.     // link into the draw list
  333.     pdeMesh->pdeNext = m_pdeHead;
  334.     m_pdeHead = pdeMesh;
  335.     
  336.     m_pdeSelected = pdeMesh;
  337.     m_pmcSelectedMesh = pdeMesh->pframeRoot->pmcMesh;
  338.     
  339.     
  340.     m_pframeSelected = pdeMesh->pframeRoot;
  341.     
  342.     hr = CalculateBoundingSphere(pdeMesh);
  343.     if (FAILED(hr))
  344.         goto e_Exit;
  345.     
  346.     SetProjectionMatrix();
  347.     
  348.     m_pdeSelected->fCurTime = 0.0f;
  349.     m_pdeSelected->fMaxTime = 200.0f;
  350.     
  351.     D3DXMatrixTranslation(&m_pdeSelected->pframeRoot->matRot,
  352.         -pdeMesh->vCenter.x, -pdeMesh->vCenter.y, -pdeMesh->vCenter.z);
  353.     m_pdeSelected->pframeRoot->matRotOrig = m_pdeSelected->pframeRoot->matRot;
  354.     
  355. e_Exit:
  356.     GXRELEASE(pxofobjCur);
  357.     GXRELEASE(pxofenum);
  358.     GXRELEASE(pxofapi);
  359.     
  360.     if (FAILED(hr))
  361.     {
  362.         delete pdeMesh;
  363.     }
  364.     
  365.     return hr;
  366. }
  367.  
  368.  
  369.  
  370.  
  371. HRESULT CMyD3DApplication::LoadAnimation(LPDIRECTXFILEDATA pxofobjCur, SDrawElement *pde,
  372.                                          DWORD options, DWORD fvf, LPDIRECT3DDEVICE8 pD3DDevice,
  373.                                          SFrame *pframeParent)
  374. {
  375.     HRESULT hr = S_OK;
  376.     SRotateKeyXFile *pFileRotateKey;
  377.     SScaleKeyXFile *pFileScaleKey;
  378.     SPositionKeyXFile *pFilePosKey;
  379.     SMatrixKeyXFile *pFileMatrixKey;
  380.     SFrame *pframeCur;
  381.     LPDIRECTXFILEDATA pxofobjChild = NULL;
  382.     LPDIRECTXFILEOBJECT pxofChild = NULL;
  383.     LPDIRECTXFILEDATAREFERENCE pxofobjChildRef = NULL;
  384.     const GUID *type;
  385.     DWORD dwSize;
  386.     PBYTE pData;
  387.     DWORD dwKeyType;
  388.     DWORD cKeys;
  389.     DWORD iKey;
  390.     DWORD cchName;
  391.     char *szFrameName;
  392.     
  393.     pframeCur = new SFrame();
  394.     if (pframeCur == NULL)
  395.     {
  396.         hr = E_OUTOFMEMORY;
  397.         goto e_Exit;
  398.     }
  399.     pframeCur->bAnimationFrame = true;
  400.     
  401.     pframeParent->AddFrame(pframeCur);
  402.     pde->AddAnimationFrame(pframeCur);
  403.     
  404.     // Enumerate child objects.
  405.     // Child object can be data, data reference or binary.
  406.     // Use QueryInterface() to find what type of object a child is.
  407.     while (SUCCEEDED(pxofobjCur->GetNextObject(&pxofChild)))
  408.     {
  409.         // Query the child for it's FileDataReference
  410.         hr = pxofChild->QueryInterface(IID_IDirectXFileDataReference,
  411.             (LPVOID *)&pxofobjChildRef);
  412.         if (SUCCEEDED(hr))
  413.         {
  414.             hr = pxofobjChildRef->Resolve(&pxofobjChild);
  415.             if (SUCCEEDED(hr))
  416.             {
  417.                 hr = pxofobjChild->GetType(&type);
  418.                 if (FAILED(hr))
  419.                     goto e_Exit;
  420.                 
  421.                 if( TID_D3DRMFrame == *type )
  422.                 {
  423.                     if (pframeCur->pframeToAnimate != NULL)
  424.                     {
  425.                         hr = E_INVALIDARG;
  426.                         goto e_Exit;
  427.                     }
  428.                     
  429.                     hr = pxofobjChild->GetName(NULL, &cchName);
  430.                     if (FAILED(hr))
  431.                         goto e_Exit;
  432.                     
  433.                     if (cchName == 0)
  434.                     {
  435.                         hr = E_INVALIDARG;
  436.                         goto e_Exit;
  437.                         
  438.                     }
  439.                     
  440.                     szFrameName = (char*)_alloca(cchName);
  441.                     if (szFrameName == NULL)
  442.                     {
  443.                         hr = E_OUTOFMEMORY;
  444.                         goto e_Exit;
  445.                     }
  446.                     
  447.                     hr = pxofobjChild->GetName(szFrameName, &cchName);
  448.                     if (FAILED(hr))
  449.                         goto e_Exit;
  450.                     
  451.                     pframeCur->pframeToAnimate = pde->FindFrame(szFrameName);
  452.                     if (pframeCur->pframeToAnimate == NULL)
  453.                     {
  454.                         hr = E_INVALIDARG;
  455.                         goto e_Exit;
  456.                     }
  457.                 }
  458.                 
  459.                 GXRELEASE(pxofobjChild);
  460.             }
  461.             
  462.             GXRELEASE(pxofobjChildRef);
  463.         }
  464.         else
  465.         {
  466.             
  467.             // Query the child for it's FileData
  468.             hr = pxofChild->QueryInterface(IID_IDirectXFileData,
  469.                 (LPVOID *)&pxofobjChild);
  470.             if (SUCCEEDED(hr))
  471.             {
  472.                 hr = pxofobjChild->GetType(&type);
  473.                 if (FAILED(hr))
  474.                     goto e_Exit;
  475.                 
  476.                 if ( TID_D3DRMFrame == *type )
  477.                 {
  478.                     hr = LoadFrames(pxofobjChild, pde, options, fvf, pD3DDevice, pframeCur);
  479.                     if (FAILED(hr))
  480.                         goto e_Exit;
  481.                 }
  482.                 else if ( TID_D3DRMAnimationOptions == *type )
  483.                 {
  484.                     //ParseAnimOptions(pChildData,pParentFrame);
  485.                     //i=2;
  486.                 }
  487.                 else if ( TID_D3DRMAnimationKey == *type )
  488.                 {
  489.                     hr = pxofobjChild->GetData( NULL, &dwSize, (PVOID*)&pData );
  490.                     if (FAILED(hr))
  491.                         goto e_Exit;
  492.                     
  493.                     dwKeyType = ((DWORD*)pData)[0];
  494.                     cKeys = ((DWORD*)pData)[1];
  495.                     
  496.                     if (dwKeyType == 0)
  497.                     {
  498.                         if (pframeCur->m_pRotateKeys != NULL)
  499.                         {
  500.                             hr = E_INVALIDARG;
  501.                             goto e_Exit;
  502.                         }
  503.                         
  504.                         pframeCur->m_pRotateKeys = new SRotateKey[cKeys];
  505.                         if (pframeCur->m_pRotateKeys == NULL)
  506.                         {
  507.                             hr = E_OUTOFMEMORY;
  508.                             goto e_Exit;
  509.                         }
  510.                         
  511.                         pframeCur->m_cRotateKeys = cKeys;
  512.                         //NOTE x files are w x y z and QUATERNIONS are x y z w
  513.                         
  514.                         pFileRotateKey =  (SRotateKeyXFile*)(pData + (sizeof(DWORD) * 2));
  515.                         for (iKey = 0;iKey < cKeys; iKey++)
  516.                         {
  517.                             pframeCur->m_pRotateKeys[iKey].dwTime = pFileRotateKey->dwTime;
  518.                             pframeCur->m_pRotateKeys[iKey].quatRotate.x = pFileRotateKey->x;
  519.                             pframeCur->m_pRotateKeys[iKey].quatRotate.y = pFileRotateKey->y;
  520.                             pframeCur->m_pRotateKeys[iKey].quatRotate.z = pFileRotateKey->z;
  521.                             pframeCur->m_pRotateKeys[iKey].quatRotate.w = pFileRotateKey->w;
  522.                             
  523.                             pFileRotateKey += 1;
  524.                         }
  525.                     }
  526.                     else if (dwKeyType == 1)
  527.                     {
  528.                         if (pframeCur->m_pScaleKeys != NULL)
  529.                         {
  530.                             hr = E_INVALIDARG;
  531.                             goto e_Exit;
  532.                         }
  533.                         
  534.                         pframeCur->m_pScaleKeys = new SScaleKey[cKeys];
  535.                         if (pframeCur->m_pScaleKeys == NULL)
  536.                         {
  537.                             hr = E_OUTOFMEMORY;
  538.                             goto e_Exit;
  539.                         }
  540.                         
  541.                         pframeCur->m_cScaleKeys = cKeys;
  542.                         
  543.                         pFileScaleKey =  (SScaleKeyXFile*)(pData + (sizeof(DWORD) * 2));
  544.                         for (iKey = 0;iKey < cKeys; iKey++)
  545.                         {
  546.                             pframeCur->m_pScaleKeys[iKey].dwTime = pFileScaleKey->dwTime;
  547.                             pframeCur->m_pScaleKeys[iKey].vScale = pFileScaleKey->vScale;
  548.                             
  549.                             pFileScaleKey += 1;
  550.                         }
  551.                     }
  552.                     else if (dwKeyType == 2)
  553.                     {
  554.                         if (pframeCur->m_pPositionKeys != NULL)
  555.                         {
  556.                             hr = E_INVALIDARG;
  557.                             goto e_Exit;
  558.                         }
  559.                         
  560.                         pframeCur->m_pPositionKeys = new SPositionKey[cKeys];
  561.                         if (pframeCur->m_pPositionKeys == NULL)
  562.                         {
  563.                             hr = E_OUTOFMEMORY;
  564.                             goto e_Exit;
  565.                         }
  566.                         
  567.                         pframeCur->m_cPositionKeys = cKeys;
  568.                         
  569.                         pFilePosKey =  (SPositionKeyXFile*)(pData + (sizeof(DWORD) * 2));
  570.                         for (iKey = 0;iKey < cKeys; iKey++)
  571.                         {
  572.                             pframeCur->m_pPositionKeys[iKey].dwTime = pFilePosKey->dwTime;
  573.                             pframeCur->m_pPositionKeys[iKey].vPos = pFilePosKey->vPos;
  574.                             
  575.                             pFilePosKey += 1;
  576.                         }
  577.                     }
  578.                     else if (dwKeyType == 4)
  579.                     {
  580.                         if (pframeCur->m_pMatrixKeys != NULL)
  581.                         {
  582.                             hr = E_INVALIDARG;
  583.                             goto e_Exit;
  584.                         }
  585.                         
  586.                         pframeCur->m_pMatrixKeys = new SMatrixKey[cKeys];
  587.                         if (pframeCur->m_pMatrixKeys == NULL)
  588.                         {
  589.                             hr = E_OUTOFMEMORY;
  590.                             goto e_Exit;
  591.                         }
  592.                         
  593.                         pframeCur->m_cMatrixKeys = cKeys;
  594.                         
  595.                         pFileMatrixKey =  (SMatrixKeyXFile*)(pData + (sizeof(DWORD) * 2));
  596.                         for (iKey = 0;iKey < cKeys; iKey++)
  597.                         {
  598.                             pframeCur->m_pMatrixKeys[iKey].dwTime = pFileMatrixKey->dwTime;
  599.                             pframeCur->m_pMatrixKeys[iKey].mat = pFileMatrixKey->mat;
  600.                             
  601.                             pFileMatrixKey += 1;
  602.                         }
  603.                     }
  604.                     else
  605.                     {
  606.                         hr = E_INVALIDARG;
  607.                         goto e_Exit;
  608.                     }
  609.                 }
  610.                 
  611.                 GXRELEASE(pxofobjChild);
  612.             }
  613.         }
  614.         
  615.         GXRELEASE(pxofChild);
  616.     }
  617.     
  618. e_Exit:
  619.     GXRELEASE(pxofobjChild);
  620.     GXRELEASE(pxofChild);
  621.     GXRELEASE(pxofobjChildRef);
  622.     return hr;
  623. }
  624.  
  625.  
  626.  
  627.  
  628. HRESULT CMyD3DApplication::LoadAnimationSet(LPDIRECTXFILEDATA pxofobjCur, SDrawElement *pde,
  629.                                             DWORD options, DWORD fvf, LPDIRECT3DDEVICE8 pD3DDevice,
  630.                                             SFrame *pframeParent)
  631. {
  632.     SFrame *pframeCur;
  633.     const GUID *type;
  634.     HRESULT hr = S_OK;
  635.     LPDIRECTXFILEDATA pxofobjChild = NULL;
  636.     LPDIRECTXFILEOBJECT pxofChild = NULL;
  637.     DWORD cchName;
  638.     
  639.     pframeCur = new SFrame();
  640.     if (pframeCur == NULL)
  641.     {
  642.         hr = E_OUTOFMEMORY;
  643.         goto e_Exit;
  644.     }
  645.     pframeCur->bAnimationFrame = true;
  646.     
  647.     pframeParent->AddFrame(pframeCur);
  648.     
  649.     hr = pxofobjCur->GetName(NULL, &cchName);
  650.     if (FAILED(hr))
  651.         goto e_Exit;
  652.     
  653.     if (cchName > 0)
  654.     {
  655.         pframeCur->szName = new char[cchName];
  656.         if (pframeCur->szName == NULL)
  657.         {
  658.             hr = E_OUTOFMEMORY;
  659.             goto e_Exit;
  660.         }
  661.         
  662.         hr = pxofobjCur->GetName(pframeCur->szName, &cchName);
  663.         if (FAILED(hr))
  664.             goto e_Exit;
  665.     }
  666.     
  667.     
  668.     // Enumerate child objects.
  669.     // Child object can be data, data reference or binary.
  670.     // Use QueryInterface() to find what type of object a child is.
  671.     while (SUCCEEDED(pxofobjCur->GetNextObject(&pxofChild)))
  672.     {
  673.         // Query the child for it's FileData
  674.         hr = pxofChild->QueryInterface(IID_IDirectXFileData,
  675.             (LPVOID *)&pxofobjChild);
  676.         if (SUCCEEDED(hr))
  677.         {
  678.             hr = pxofobjChild->GetType(&type);
  679.             if (FAILED(hr))
  680.                 goto e_Exit;
  681.             
  682.             if( TID_D3DRMAnimation == *type )
  683.             {
  684.                 hr = LoadAnimation(pxofobjChild, pde, options, fvf, pD3DDevice, pframeCur);
  685.                 if (FAILED(hr))
  686.                     goto e_Exit;
  687.             }
  688.             
  689.             GXRELEASE(pxofobjChild);
  690.         }
  691.         
  692.         GXRELEASE(pxofChild);
  693.     }
  694.     
  695. e_Exit:
  696.     GXRELEASE(pxofobjChild);
  697.     GXRELEASE(pxofChild);
  698.     return hr;
  699. }
  700.  
  701.  
  702.  
  703.  
  704. HRESULT SplitMesh
  705.         (
  706.             LPD3DXMESH  pMesh,              // ASSUMPTION:  *pMesh is attribute sorted & has a valid attribute table
  707.             DWORD       iAttrSplit,         // **ppMeshB gets the mesh comprising of this attribute range onward
  708.             DWORD*      rgiAdjacency, 
  709.             DWORD       optionsA, 
  710.             DWORD       optionsB, 
  711.             LPD3DXMESH* ppMeshA, 
  712.             LPD3DXMESH* ppMeshB
  713.         )
  714. {
  715.     HRESULT hr  = S_OK;
  716.     PBYTE   pbVerticesIn    = NULL;
  717.     PBYTE   pbIndicesIn     = NULL;
  718.     DWORD*  piAttribsIn     = NULL;
  719.     LPD3DXMESH pMeshA   = NULL;
  720.     LPD3DXMESH pMeshB   = NULL;
  721.     LPD3DXBUFFER pVertexRemapA  = NULL;
  722.     LPD3DXBUFFER pVertexRemapB  = NULL;
  723.     DWORD*  rgiAdjacencyA   = NULL;
  724.     DWORD*  rgiAdjacencyB   = NULL;
  725.     LPDIRECT3DDEVICE8   pDevice     = NULL;
  726.     D3DXATTRIBUTERANGE* rgAttrTable = NULL;
  727.     DWORD               cAttrTable  = 0;
  728.     DWORD   cVerticesA;
  729.     DWORD   cVerticesB;
  730.     DWORD   cFacesA;
  731.     DWORD   cFacesB;
  732.     DWORD   cbVertexSize;
  733.     DWORD   dw32bit;
  734.  
  735.     *ppMeshA = NULL;
  736.     *ppMeshB = NULL;
  737.     dw32bit         = pMesh->GetOptions() & D3DXMESH_32BIT;
  738.     cbVertexSize    = D3DXGetFVFVertexSize(pMesh->GetFVF());
  739.  
  740.     hr  = pMesh->GetDevice(&pDevice);
  741.     if (FAILED(hr))
  742.         goto e_Exit;
  743.  
  744.     hr  = pMesh->GetAttributeTable(NULL, &cAttrTable);
  745.     if (FAILED(hr))
  746.         goto e_Exit;
  747.     
  748.     rgAttrTable = new D3DXATTRIBUTERANGE[cAttrTable];
  749.     if (rgAttrTable == NULL)
  750.     {
  751.         hr  = E_OUTOFMEMORY;
  752.  
  753.         goto e_Exit;
  754.     }
  755.  
  756.     hr  = pMesh->GetAttributeTable(rgAttrTable, NULL);
  757.     if (FAILED(hr))
  758.         goto e_Exit;
  759.  
  760.     if (iAttrSplit == 0)
  761.     {
  762.         cVerticesA  = 0;
  763.         cFacesA     = 0;
  764.     }
  765.     else if (iAttrSplit >= cAttrTable)
  766.     {
  767.         cVerticesA  = pMesh->GetNumVertices();
  768.         cFacesA     = pMesh->GetNumFaces();
  769.     }
  770.     else
  771.     {
  772.         cVerticesA  = rgAttrTable[iAttrSplit].VertexStart;
  773.         cFacesA     = rgAttrTable[iAttrSplit].FaceStart;
  774.     }
  775.  
  776.     cVerticesB  = pMesh->GetNumVertices() - cVerticesA;
  777.     cFacesB     = pMesh->GetNumFaces() - cFacesA;
  778.  
  779.     hr  = pMesh->LockVertexBuffer(D3DLOCK_READONLY, &pbVerticesIn);
  780.     if (FAILED(hr))
  781.         goto e_Exit;
  782.  
  783.     hr  = pMesh->LockIndexBuffer(D3DLOCK_READONLY, &pbIndicesIn);
  784.     if (FAILED(hr))
  785.         goto e_Exit;
  786.  
  787.     hr  = pMesh->LockAttributeBuffer(D3DLOCK_READONLY, &piAttribsIn);
  788.     if (FAILED(hr))
  789.         goto e_Exit;
  790.  
  791.     if (cFacesA && cVerticesA)
  792.     {
  793.         PBYTE   pbVerticesOut   = NULL;
  794.         PBYTE   pbIndicesOut    = NULL;
  795.         DWORD*  piAttribsOut    = NULL;
  796.         DWORD i;
  797.  
  798.         hr  = D3DXCreateMeshFVF(cFacesA, cVerticesA, D3DXMESH_SYSTEMMEM | dw32bit, pMesh->GetFVF(), pDevice, &pMeshA);
  799.         if (FAILED(hr))
  800.             goto e_ExitA;
  801.  
  802.         hr  = pMeshA->LockVertexBuffer(0, &pbVerticesOut);
  803.         if (FAILED(hr))
  804.             goto e_ExitA;
  805.  
  806.         hr  = pMeshA->LockIndexBuffer(0, (LPBYTE*)&pbIndicesOut);
  807.         if (FAILED(hr))
  808.             goto e_ExitA;
  809.  
  810.         hr  = pMeshA->LockAttributeBuffer(0, &piAttribsOut);
  811.         if (FAILED(hr))
  812.             goto e_ExitA;
  813.  
  814.         memcpy(pbVerticesOut, pbVerticesIn, cVerticesA * cbVertexSize * sizeof(BYTE));
  815.  
  816.         if (dw32bit)
  817.         {
  818.             memcpy(pbIndicesOut, pbIndicesIn, cFacesA * 3 * sizeof(DWORD));
  819.         }
  820.         else
  821.         {
  822.             memcpy(pbIndicesOut, pbIndicesIn, cFacesA * 3 * sizeof(WORD));
  823.         }
  824.  
  825.         memcpy(piAttribsOut, piAttribsIn, cFacesA * sizeof(DWORD));
  826.         rgiAdjacencyA   = new DWORD[cFacesA * 3];
  827.  
  828.         if (rgiAdjacencyA == NULL)
  829.         {
  830.             hr  = E_OUTOFMEMORY;
  831.             goto e_ExitA;
  832.         }
  833.  
  834.         for (i = 0; i <  cFacesA * 3; i++)
  835.         {
  836.             rgiAdjacencyA[i]    = (rgiAdjacency[i] < cFacesA) ? rgiAdjacency[i] : 0xFFFFFFFF;
  837.         }
  838.  
  839. e_ExitA:
  840.         if (pbVerticesOut != NULL)
  841.         {
  842.             pMeshA->UnlockVertexBuffer();
  843.         }
  844.  
  845.         if (pbIndicesOut != NULL)
  846.         {
  847.             pMeshA->UnlockIndexBuffer();
  848.         }
  849.  
  850.         if (piAttribsOut != NULL)
  851.         {
  852.             pMeshA->UnlockAttributeBuffer();
  853.         }
  854.  
  855.         if (FAILED(hr))
  856.             goto e_Exit;
  857.     }
  858.  
  859.     // calculate Mesh A's attribute table
  860.  
  861.     if (pMeshA != NULL)
  862.     {
  863.         hr  = pMeshA->OptimizeInplace
  864.                       (
  865.                           D3DXMESHOPT_VERTEXCACHE,
  866.                           rgiAdjacencyA,
  867.                           NULL,
  868.                           NULL,
  869.                           &pVertexRemapA
  870.                       );
  871.         if (FAILED(hr))
  872.             goto e_Exit;
  873.  
  874.         hr = pMeshA->CloneMeshFVF(optionsA, pMeshA->GetFVF(), pDevice, ppMeshA);
  875.         if (FAILED(hr))
  876.             goto e_Exit;
  877.  
  878.         GXRELEASE(pMeshA);
  879.     }
  880.  
  881.     if (cFacesB && cVerticesB)
  882.     {
  883.         PBYTE   pbVerticesOut   = NULL;
  884.         PBYTE   pbIndicesOut    = NULL;
  885.         DWORD*  piAttribsOut    = NULL;
  886.         DWORD i;
  887.  
  888.         hr  = D3DXCreateMeshFVF(cFacesB, cVerticesB, D3DXMESH_SYSTEMMEM | dw32bit, pMesh->GetFVF(), pDevice, &pMeshB);
  889.         if (FAILED(hr))
  890.             goto e_ExitB;
  891.  
  892.         hr  = pMeshB->LockVertexBuffer(0, &pbVerticesOut);
  893.         if (FAILED(hr))
  894.             goto e_ExitB;
  895.  
  896.         hr  = pMeshB->LockIndexBuffer(0, &pbIndicesOut);
  897.         if (FAILED(hr))
  898.             goto e_ExitB;
  899.  
  900.         hr  = pMeshB->LockAttributeBuffer(0, &piAttribsOut);
  901.         if (FAILED(hr))
  902.             goto e_ExitB;
  903.  
  904.         memcpy(pbVerticesOut, pbVerticesIn + (cVerticesA * cbVertexSize), cVerticesB * cbVertexSize * sizeof(BYTE));
  905.  
  906.         // copy & renumber indices
  907.  
  908.         if (dw32bit)
  909.         {
  910.             for (DWORD i = 0; i < cFacesB * 3; i++)
  911.             {
  912.                 ((DWORD*)pbIndicesOut)[i]    = ((DWORD*)pbIndicesIn)[(cFacesA * 3) + i]  - (DWORD)cVerticesA;
  913.             }
  914.         }
  915.         else
  916.         {
  917.             for (DWORD i = 0; i < cFacesB * 3; i++)
  918.             {
  919.                 ((WORD*)pbIndicesOut)[i]    = ((WORD*)pbIndicesIn)[(cFacesA * 3) + i]  - (WORD)cVerticesA;
  920.             }
  921.         }
  922.  
  923.         memcpy(piAttribsOut, piAttribsIn + cFacesA, cFacesB * sizeof(DWORD));
  924.         rgiAdjacencyB   = new DWORD[cFacesB * 3];
  925.  
  926.         if (rgiAdjacencyB == NULL)
  927.         {
  928.             hr  = E_OUTOFMEMORY;
  929.             goto e_ExitB;
  930.         }
  931.  
  932.         // copy & renumber adjacency
  933.  
  934.         for (i = 0; i < cFacesB * 3; i++)
  935.         {
  936.             rgiAdjacencyB[i]    = (rgiAdjacency[(cFacesA * 3) + i] >= cFacesA && rgiAdjacency[(cFacesA * 3) + i] != 0xFFFFFFFF) ? rgiAdjacency[(cFacesA * 3) + i] - cFacesA : 0xFFFFFFFF;
  937.         }
  938.  
  939. e_ExitB:
  940.         if (pbVerticesOut != NULL)
  941.         {
  942.             pMeshB->UnlockVertexBuffer();
  943.         }
  944.  
  945.         if (pbIndicesOut != NULL)
  946.         {
  947.             pMeshB->UnlockIndexBuffer();
  948.         }
  949.  
  950.         if (piAttribsOut != NULL)
  951.         {
  952.             pMeshB->UnlockAttributeBuffer();
  953.         }
  954.  
  955.         if (FAILED(hr))
  956.             goto e_Exit;
  957.     }
  958.  
  959.     // calculate Mesh B's attribute table
  960.  
  961.     if (pMeshB != NULL)
  962.     {
  963.         hr  = pMeshB->OptimizeInplace
  964.                       (
  965.                           D3DXMESHOPT_VERTEXCACHE,
  966.                           rgiAdjacencyB,
  967.                           NULL,
  968.                           NULL,
  969.                           &pVertexRemapB
  970.                       );
  971.         if (FAILED(hr))
  972.             goto e_Exit;
  973.         
  974.         hr = pMeshB->CloneMeshFVF(optionsB, pMeshB->GetFVF(), pDevice, ppMeshB);
  975.         if (FAILED(hr))
  976.             goto e_Exit;
  977.  
  978.         GXRELEASE(pMeshB);
  979.     }
  980.  
  981. e_Exit:    
  982.     if (rgAttrTable != NULL)
  983.     {
  984.         delete[] rgAttrTable;
  985.     }
  986.  
  987.     if (pbVerticesIn != NULL)
  988.     {
  989.         pMesh->UnlockVertexBuffer();
  990.     }
  991.  
  992.     if (pbIndicesIn != NULL)
  993.     {
  994.         pMesh->UnlockIndexBuffer();
  995.     }
  996.  
  997.     if (piAttribsIn != NULL)
  998.     {
  999.         pMesh->UnlockAttributeBuffer();
  1000.     }
  1001.     
  1002.     if (rgiAdjacencyA != NULL)
  1003.     {
  1004.         delete[] rgiAdjacencyA;
  1005.     }
  1006.  
  1007.     if (rgiAdjacencyB != NULL)
  1008.     {
  1009.         delete[] rgiAdjacencyB;
  1010.     }
  1011.  
  1012.     GXRELEASE(pDevice);
  1013.     GXRELEASE(pVertexRemapA);
  1014.     GXRELEASE(pVertexRemapB);
  1015.  
  1016.     if (FAILED(hr))
  1017.     {
  1018.         GXRELEASE(pMeshA);
  1019.         GXRELEASE(pMeshB);
  1020.         pMeshA  = NULL;
  1021.         pMeshB  = NULL;
  1022.     }
  1023.  
  1024.     return hr;
  1025. }
  1026.  
  1027.  
  1028.  
  1029.  
  1030. HRESULT CMyD3DApplication::GenerateMesh(SMeshContainer *pmcMesh)
  1031. {
  1032.     // ASSUMPTION:  pmcMesh->m_rgiAdjacency contains the current adjacency
  1033.     HRESULT hr = S_OK;
  1034.     D3DCAPS8 caps;
  1035.     LPDIRECT3DDEVICE8 pDevice = NULL;
  1036.     DWORD* pAdjacencyIn = NULL;
  1037.     DWORD cFaces = pmcMesh->m_pSkinMesh->GetNumFaces();
  1038.  
  1039.     pAdjacencyIn    = new DWORD[pmcMesh->m_pSkinMesh->GetNumFaces() * 3];
  1040.     if (pAdjacencyIn == NULL)
  1041.     {
  1042.         hr = E_OUTOFMEMORY;
  1043.         goto e_Exit;
  1044.     }
  1045.     
  1046.     memcpy(pAdjacencyIn, pmcMesh->m_rgiAdjacency, cFaces * 3 * sizeof(DWORD));
  1047.  
  1048.     hr  = pmcMesh->m_pSkinMesh->GetDevice(&pDevice);
  1049.     if (FAILED(hr))
  1050.         goto e_Exit;
  1051.  
  1052.     // Make sure we get HW caps
  1053.     hr  = pDevice->SetRenderState(D3DRS_SOFTWAREVERTEXPROCESSING, FALSE);
  1054.     if (FAILED(hr))
  1055.         goto e_Exit;
  1056.  
  1057.     hr  = pDevice->GetDeviceCaps(&caps);
  1058.     if (FAILED(hr))
  1059.         goto e_Exit;
  1060.  
  1061.     GXRELEASE(pmcMesh->pMesh);
  1062.     GXRELEASE(pmcMesh->pMeshSW);
  1063.     delete [] m_pBoneMatrices;
  1064.  
  1065.     pmcMesh->pMesh      = NULL;
  1066.     pmcMesh->pMeshSW    = NULL;
  1067.     m_pBoneMatrices     = NULL;
  1068.     
  1069.     if (m_method == D3DNONINDEXED)
  1070.     {
  1071.         DWORD*  rgiAdjacency    = NULL;
  1072.         LPD3DXBONECOMBINATION   rgBoneCombinations;
  1073.  
  1074.         rgiAdjacency    = new DWORD[cFaces * 3];
  1075.         if (rgiAdjacency == NULL)
  1076.         {
  1077.             hr  = E_OUTOFMEMORY;
  1078.             goto e_ExitNONINDEXED;
  1079.         }
  1080.  
  1081.         hr = pmcMesh->m_pSkinMesh->ConvertToBlendedMesh
  1082.                                    (
  1083.                                        0, 
  1084.                                        pAdjacencyIn, 
  1085.                                        rgiAdjacency, 
  1086.                                        &pmcMesh->cpattr, 
  1087.                                        &pmcMesh->m_pBoneCombinationBuf, 
  1088.                                        &pmcMesh->pMesh
  1089.                                    );
  1090.         if (FAILED(hr))
  1091.             goto e_ExitNONINDEXED;
  1092.  
  1093.         // calculate the max face influence count
  1094.  
  1095.         if ((pmcMesh->pMesh->GetFVF() & D3DFVF_POSITION_MASK) != D3DFVF_XYZ)
  1096.         {
  1097.             pmcMesh->m_maxFaceInfl = 1 + ((pmcMesh->pMesh->GetFVF() & D3DFVF_POSITION_MASK) - D3DFVF_XYZRHW) / 2;
  1098.         }
  1099.         else
  1100.         {
  1101.             pmcMesh->m_maxFaceInfl = 1;
  1102.         }
  1103.  
  1104.         /* If the device can only do 2 matrix blends, ConvertToBlendedMesh cannot approximate all meshes to it
  1105.            Thus we split the mesh in two parts: The part that uses at most 2 matrices and the rest. The first is
  1106.            drawn using the device's HW vertex processing and the rest is drawn using SW vertex processing. */
  1107.         if (caps.MaxVertexBlendMatrices == 2)       
  1108.         {
  1109.             // calculate the index of the attribute table to split on
  1110.             rgBoneCombinations  = reinterpret_cast<LPD3DXBONECOMBINATION>(pmcMesh->m_pBoneCombinationBuf->GetBufferPointer());
  1111.  
  1112.             for (pmcMesh->iAttrSplit = 0; pmcMesh->iAttrSplit < pmcMesh->cpattr; pmcMesh->iAttrSplit++)
  1113.             {
  1114.                 DWORD   cInfl   = 0;
  1115.  
  1116.                 for (DWORD iInfl = 0; iInfl < pmcMesh->m_maxFaceInfl; iInfl++)
  1117.                 {
  1118.                     if (rgBoneCombinations[pmcMesh->iAttrSplit].BoneId[iInfl] != UINT_MAX)
  1119.                     {
  1120.                         ++cInfl;
  1121.                     }
  1122.                 }
  1123.  
  1124.                 if (cInfl > 2)
  1125.                 {
  1126.                     break;
  1127.                 }
  1128.             }
  1129.  
  1130.             // split the mesh
  1131.             LPD3DXMESH pMeshHW = NULL;
  1132.             hr  = SplitMesh(pmcMesh->pMesh, pmcMesh->iAttrSplit, rgiAdjacency, D3DXMESH_WRITEONLY,  pmcMesh->pMesh->GetOptions() | D3DXMESH_SYSTEMMEM, &pMeshHW, &pmcMesh->pMeshSW);
  1133.             if (FAILED(hr))
  1134.                 goto e_ExitNONINDEXED;
  1135.             pmcMesh->pMesh->Release();
  1136.             pmcMesh->pMesh = pMeshHW;
  1137.             pMeshHW = NULL;
  1138.         }
  1139.         else
  1140.         {
  1141.             pmcMesh->iAttrSplit = pmcMesh->cpattr;
  1142.  
  1143.             // Vertex cache optimize the mesh
  1144.             LPD3DXMESH pMeshOpt;
  1145.             hr = pmcMesh->pMesh->Optimize(D3DXMESHOPT_VERTEXCACHE, rgiAdjacency, NULL, NULL, NULL, &pMeshOpt);
  1146.             if (!FAILED(hr))
  1147.             {
  1148.                 pmcMesh->pMesh->Release();
  1149.                 pmcMesh->pMesh = pMeshOpt;
  1150.                 pMeshOpt = NULL;
  1151.             }
  1152.  
  1153.             // Need to clone the mesh to be WRITEONLY since we will not now read back from it.
  1154.              LPD3DXMESH pMeshVid;
  1155.             hr = pmcMesh->pMesh->CloneMeshFVF(pmcMesh->pMesh->GetOptions() | D3DXMESH_WRITEONLY, pmcMesh->pMesh->GetFVF(),
  1156.                                               pDevice, &pMeshVid);
  1157.             if (!FAILED(hr))
  1158.             {
  1159.                 pmcMesh->pMesh->Release();
  1160.                 pmcMesh->pMesh = pMeshVid;
  1161.                 pMeshVid = NULL;
  1162.             }
  1163.         }
  1164.  
  1165. e_ExitNONINDEXED:
  1166.  
  1167.         if (rgiAdjacency != NULL)
  1168.         {
  1169.             delete[] rgiAdjacency;
  1170.         }
  1171.  
  1172.         if (FAILED(hr))
  1173.             goto e_Exit;
  1174.  
  1175.     }
  1176.     else if (m_method == D3DINDEXED)
  1177.     {
  1178.         DWORD maxFaceInfl;
  1179.  
  1180.         hr = pmcMesh->m_pSkinMesh->GetMaxFaceInfluences(&maxFaceInfl);
  1181.         if (FAILED(hr))
  1182.             goto e_Exit;
  1183.  
  1184.         // 12 entry palette guarantees that any triangle (4 independent influences per vertex of a tri)
  1185.         // can be handled
  1186.         maxFaceInfl = min(maxFaceInfl, 12);
  1187.  
  1188.         if (caps.MaxVertexBlendMatrixIndex + 1 < maxFaceInfl)
  1189.         {
  1190.             // HW does not support indexed vertex blending. Use SW instead
  1191.             pmcMesh->m_paletteSize = min(256, pmcMesh->m_pSkinMesh->GetNumBones());
  1192.             pmcMesh->m_bUseSW = true;
  1193.         }
  1194.         else
  1195.         {
  1196.             pmcMesh->m_paletteSize = min(caps.MaxVertexBlendMatrixIndex + 1, pmcMesh->m_pSkinMesh->GetNumBones());
  1197.             pmcMesh->m_bUseSW = false;
  1198.         }
  1199.  
  1200.         DWORD options = D3DXMESH_WRITEONLY | ((pmcMesh->m_bUseSW)? D3DXMESH_SYSTEMMEM : 0);
  1201.         hr = pmcMesh->m_pSkinMesh->ConvertToIndexedBlendedMesh(options, pAdjacencyIn, pmcMesh->m_paletteSize, NULL,
  1202.             &pmcMesh->cpattr, &pmcMesh->m_pBoneCombinationBuf, &pmcMesh->pMesh);
  1203.         if (FAILED(hr))
  1204.             goto e_Exit;
  1205.  
  1206.         // Here we are talking of max vertex influence which we determine from 
  1207.         // the FVF of the returned mesh
  1208.         if ((pmcMesh->pMesh->GetFVF() & D3DFVF_POSITION_MASK) != D3DFVF_XYZ)
  1209.         {
  1210.             pmcMesh->m_maxFaceInfl = ((pmcMesh->pMesh->GetFVF() & D3DFVF_POSITION_MASK) - D3DFVF_XYZRHW) / 2;
  1211.         }
  1212.         else
  1213.         {
  1214.             pmcMesh->m_maxFaceInfl = 1;
  1215.         }
  1216.     }
  1217.     else if (m_method == SOFTWARE)
  1218.     {
  1219.         hr = pmcMesh->m_pSkinMesh->GenerateSkinnedMesh
  1220.                                    (
  1221.                                        D3DXMESH_WRITEONLY,          // options
  1222.                                        0.0f,                        // minimumm bone weight allowed
  1223.                                        pAdjacencyIn,                // adjacency of in-mesh
  1224.                                        pmcMesh->m_rgiAdjacency,     // adjacency of out-mesh
  1225.                                        &pmcMesh->pMesh              // out-mesh
  1226.                                    );
  1227.         if (FAILED(hr))
  1228.             goto e_Exit;
  1229.  
  1230.         hr = pmcMesh->pMesh->GetAttributeTable(NULL, &pmcMesh->cpattr);
  1231.         if (FAILED(hr))
  1232.             goto e_Exit;
  1233.  
  1234.         delete[] pmcMesh->m_pAttrTable;
  1235.         pmcMesh->m_pAttrTable  = new D3DXATTRIBUTERANGE[pmcMesh->cpattr];
  1236.         if (pmcMesh->m_pAttrTable == NULL)
  1237.         {
  1238.             hr = E_OUTOFMEMORY;
  1239.             goto e_Exit;
  1240.         }
  1241.  
  1242.         hr = pmcMesh->pMesh->GetAttributeTable(pmcMesh->m_pAttrTable, NULL);
  1243.         if (FAILED(hr))
  1244.             goto e_Exit;
  1245.  
  1246.         hr = pmcMesh->m_pSkinMesh->GetMaxFaceInfluences(&pmcMesh->m_maxFaceInfl);
  1247.         if (FAILED(hr))
  1248.             goto e_Exit;
  1249.  
  1250.         // Allocate space for blend matrices
  1251.         m_pBoneMatrices  = new D3DXMATRIX[m_maxBones];
  1252.         if (m_pBoneMatrices == NULL)
  1253.         {
  1254.             hr = E_OUTOFMEMORY;
  1255.             goto e_Exit;
  1256.         }
  1257.     }
  1258.     pmcMesh->m_Method = m_method;
  1259.  
  1260. e_Exit:
  1261.  
  1262.     GXRELEASE(pDevice);
  1263.     delete[] pAdjacencyIn;
  1264.     return hr;
  1265. }
  1266.  
  1267.  
  1268.  
  1269.  
  1270. HRESULT CMyD3DApplication::LoadMesh(LPDIRECTXFILEDATA pxofobjCur,
  1271.                                     DWORD options, DWORD fvf, LPDIRECT3DDEVICE8 pD3DDevice,
  1272.                                     SFrame *pframeParent)
  1273. {
  1274.     HRESULT hr = S_OK;
  1275.     SMeshContainer *pmcMesh = NULL;
  1276.     LPD3DXBUFFER pbufMaterials = NULL;
  1277.     LPD3DXBUFFER pbufAdjacency = NULL;
  1278.     DWORD cchName;
  1279.     UINT cFaces;
  1280.     UINT iMaterial;
  1281.     LPDIRECT3DDEVICE8 m_pDevice = m_pd3dDevice;
  1282.     LPDWORD pAdjacencyIn;
  1283.     
  1284.     pmcMesh = new SMeshContainer();
  1285.     if (pmcMesh == NULL)
  1286.     {
  1287.         hr = E_OUTOFMEMORY;
  1288.         goto e_Exit;
  1289.     }
  1290.     
  1291.     hr = pxofobjCur->GetName(NULL, &cchName);
  1292.     if (FAILED(hr))
  1293.         goto e_Exit;
  1294.     
  1295.     if (cchName > 0)
  1296.     {
  1297.         pmcMesh->szName = new char[cchName];
  1298.         if (pmcMesh->szName == NULL)
  1299.         {
  1300.             hr = E_OUTOFMEMORY;
  1301.             goto e_Exit;
  1302.         }
  1303.         
  1304.         hr = pxofobjCur->GetName(pmcMesh->szName, &cchName);
  1305.         if (FAILED(hr))
  1306.             goto e_Exit;
  1307.     }
  1308.     
  1309.     hr = D3DXLoadSkinMeshFromXof(pxofobjCur, options, pD3DDevice, &pbufAdjacency, &pbufMaterials, &pmcMesh->cMaterials, 
  1310.         &pmcMesh->m_pBoneNamesBuf, &pmcMesh->m_pBoneOffsetBuf, &pmcMesh->m_pSkinMesh);
  1311.     if (FAILED(hr))
  1312.         goto e_Exit;
  1313.     
  1314.     cFaces = pmcMesh->m_pSkinMesh->GetNumFaces();
  1315.  
  1316.     pAdjacencyIn = static_cast<LPDWORD>(pbufAdjacency->GetBufferPointer());
  1317.  
  1318.     pmcMesh->m_rgiAdjacency = new DWORD[cFaces * 3];
  1319.  
  1320.     if (pmcMesh->m_rgiAdjacency == NULL)
  1321.     {
  1322.         hr = E_OUTOFMEMORY;
  1323.  
  1324.         goto e_Exit;
  1325.     }
  1326.  
  1327.     memcpy(pmcMesh->m_rgiAdjacency, pAdjacencyIn, cFaces * 3 * sizeof(DWORD));
  1328.  
  1329.     // Process skinning data
  1330.     if (pmcMesh->m_pSkinMesh->GetNumBones())
  1331.     {
  1332.         // Update max bones of any mesh in the app
  1333.         m_maxBones = max(pmcMesh->m_pSkinMesh->GetNumBones(), m_maxBones);
  1334.         
  1335.         pmcMesh->m_pBoneMatrix = new D3DXMATRIX*[pmcMesh->m_pSkinMesh->GetNumBones()];
  1336.         if (pmcMesh->m_pBoneMatrix == NULL)
  1337.             goto e_Exit;
  1338.         pmcMesh->m_pBoneOffsetMat = reinterpret_cast<D3DXMATRIX*>(pmcMesh->m_pBoneOffsetBuf->GetBufferPointer());
  1339.         
  1340.         hr = GenerateMesh(pmcMesh);
  1341.  
  1342.         if (FAILED(hr))
  1343.             goto e_Exit;
  1344.     }
  1345.     else
  1346.     {
  1347.         pmcMesh->m_pSkinMesh->GetOriginalMesh(&(pmcMesh->pMesh));
  1348.         pmcMesh->m_pSkinMesh->Release();
  1349.         pmcMesh->m_pSkinMesh = NULL;
  1350.         pmcMesh->cpattr = pmcMesh->cMaterials;
  1351.     }
  1352.     
  1353.     if ((pbufMaterials == NULL) || (pmcMesh->cMaterials == 0))
  1354.     {
  1355.         pmcMesh->rgMaterials = new D3DMATERIAL8[1];
  1356.         pmcMesh->pTextures = new LPDIRECT3DTEXTURE8[1];
  1357.         if (pmcMesh->rgMaterials == NULL || pmcMesh->pTextures == NULL)
  1358.         {
  1359.             hr = E_OUTOFMEMORY;
  1360.             goto e_Exit;
  1361.         }
  1362.         
  1363.         memset(pmcMesh->rgMaterials, 0, sizeof(D3DMATERIAL8));
  1364.         pmcMesh->rgMaterials[0].Diffuse.r = 0.5f;
  1365.         pmcMesh->rgMaterials[0].Diffuse.g = 0.5f;
  1366.         pmcMesh->rgMaterials[0].Diffuse.b = 0.5f;
  1367.         pmcMesh->rgMaterials[0].Specular = pmcMesh->rgMaterials[0].Diffuse;
  1368.         pmcMesh->pTextures[0] = NULL;
  1369.     }
  1370.     else
  1371.     {
  1372.         pmcMesh->rgMaterials = new D3DMATERIAL8[pmcMesh->cMaterials];
  1373.         pmcMesh->pTextures = new LPDIRECT3DTEXTURE8[pmcMesh->cMaterials];
  1374.         if (pmcMesh->rgMaterials == NULL || pmcMesh->pTextures == NULL)
  1375.         {
  1376.             hr = E_OUTOFMEMORY;
  1377.             goto e_Exit;
  1378.         }
  1379.         
  1380.         LPD3DXMATERIAL pMaterials = (LPD3DXMATERIAL)pbufMaterials->GetBufferPointer();
  1381.         
  1382.         for (iMaterial = 0; iMaterial < pmcMesh->cMaterials; iMaterial++)
  1383.         {
  1384.             
  1385.             pmcMesh->rgMaterials[iMaterial] = pMaterials[iMaterial].MatD3D;
  1386.             
  1387.             pmcMesh->pTextures[iMaterial] = NULL;
  1388.             if (pMaterials[iMaterial].pTextureFilename != NULL)
  1389.             {
  1390.                 TCHAR szPath[MAX_PATH];
  1391.                 DXUtil_FindMediaFile(szPath, pMaterials[iMaterial].pTextureFilename);
  1392.  
  1393.                 hr = D3DXCreateTextureFromFile(m_pDevice, szPath, &(pmcMesh->pTextures[iMaterial]));
  1394.                 if (FAILED(hr))
  1395.                     pmcMesh->pTextures[iMaterial] = NULL;
  1396.             }
  1397.         }
  1398.     }
  1399.     
  1400.     // add the mesh to the parent frame
  1401.     pframeParent->AddMesh(pmcMesh);
  1402.     pmcMesh = NULL;
  1403.     
  1404. e_Exit:
  1405.     delete pmcMesh;
  1406.     
  1407.     GXRELEASE(pbufAdjacency);
  1408.     GXRELEASE(pbufMaterials);
  1409.  
  1410.     return hr;
  1411. }
  1412.  
  1413.  
  1414.  
  1415.  
  1416. HRESULT CMyD3DApplication::LoadFrames(LPDIRECTXFILEDATA pxofobjCur, SDrawElement *pde,
  1417.                                       DWORD options, DWORD fvf, LPDIRECT3DDEVICE8 pD3DDevice,
  1418.                                       SFrame *pframeParent)
  1419. {
  1420.     HRESULT hr = S_OK;
  1421.     LPDIRECTXFILEDATA pxofobjChild = NULL;
  1422.     LPDIRECTXFILEOBJECT pxofChild = NULL;
  1423.     const GUID *type;
  1424.     DWORD cbSize;
  1425.     D3DXMATRIX *pmatNew;
  1426.     SFrame *pframeCur;
  1427.     DWORD cchName;
  1428.     
  1429.     // Get the type of the object
  1430.     hr = pxofobjCur->GetType(&type);
  1431.     if (FAILED(hr))
  1432.         goto e_Exit;
  1433.     
  1434.     
  1435.     if (*type == TID_D3DRMMesh)
  1436.     {
  1437.         hr = LoadMesh(pxofobjCur, options, fvf, pD3DDevice, pframeParent);
  1438.         if (FAILED(hr))
  1439.             goto e_Exit;
  1440.     }
  1441.     else if (*type == TID_D3DRMFrameTransformMatrix)
  1442.     {
  1443.         hr = pxofobjCur->GetData(NULL, &cbSize, (PVOID*)&pmatNew);
  1444.         if (FAILED(hr))
  1445.             goto e_Exit;
  1446.         
  1447.         // update the parents matrix with the new one
  1448.         pframeParent->matRot = *pmatNew;
  1449.         pframeParent->matRotOrig = *pmatNew;
  1450.     }
  1451.     else if (*type == TID_D3DRMAnimationSet)
  1452.     {
  1453.         LoadAnimationSet(pxofobjCur, pde, options, fvf, pD3DDevice, pframeParent);
  1454.     }
  1455.     else if (*type == TID_D3DRMAnimation)
  1456.     {
  1457.         LoadAnimation(pxofobjCur, pde, options, fvf, pD3DDevice, pframeParent);
  1458.     }
  1459.     else if (*type == TID_D3DRMFrame)
  1460.     {
  1461.         pframeCur = new SFrame();
  1462.         if (pframeCur == NULL)
  1463.         {
  1464.             hr = E_OUTOFMEMORY;
  1465.             goto e_Exit;
  1466.         }
  1467.         
  1468.         hr = pxofobjCur->GetName(NULL, &cchName);
  1469.         if (FAILED(hr))
  1470.             goto e_Exit;
  1471.         
  1472.         if (cchName > 0)
  1473.         {
  1474.             pframeCur->szName = new char[cchName];
  1475.             if (pframeCur->szName == NULL)
  1476.             {
  1477.                 hr = E_OUTOFMEMORY;
  1478.                 goto e_Exit;
  1479.             }
  1480.             
  1481.             hr = pxofobjCur->GetName(pframeCur->szName, &cchName);
  1482.             if (FAILED(hr))
  1483.                 goto e_Exit;
  1484.         }
  1485.         
  1486.         pframeParent->AddFrame(pframeCur);
  1487.         
  1488.         // Enumerate child objects.
  1489.         // Child object can be data, data reference or binary.
  1490.         // Use QueryInterface() to find what type of object a child is.
  1491.         while (SUCCEEDED(pxofobjCur->GetNextObject(&pxofChild)))
  1492.         {
  1493.             // Query the child for it's FileData
  1494.             hr = pxofChild->QueryInterface(IID_IDirectXFileData,
  1495.                 (LPVOID *)&pxofobjChild);
  1496.             if (SUCCEEDED(hr))
  1497.             {
  1498.                 hr = LoadFrames(pxofobjChild, pde, options, fvf, pD3DDevice, pframeCur);
  1499.                 if (FAILED(hr))
  1500.                     goto e_Exit;
  1501.                 
  1502.                 GXRELEASE(pxofobjChild);
  1503.             }
  1504.             
  1505.             GXRELEASE(pxofChild);
  1506.         }
  1507.         
  1508.     }
  1509.     
  1510. e_Exit:
  1511.     GXRELEASE(pxofobjChild);
  1512.     GXRELEASE(pxofChild);
  1513.     return hr;
  1514. }
  1515.  
  1516.  
  1517.          
  1518.                                       
  1519. HRESULT  CMyD3DApplication::DeleteSelectedMesh()
  1520. {
  1521.     if (m_pdeSelected != NULL)
  1522.     {
  1523.         SDrawElement *pdeCur = m_pdeHead;
  1524.         SDrawElement *pdePrev = NULL;
  1525.         while ((pdeCur != NULL) && (pdeCur != m_pdeSelected))
  1526.         {
  1527.             pdePrev = pdeCur;
  1528.             pdeCur = pdeCur->pdeNext;
  1529.         }
  1530.  
  1531.         if (pdePrev == NULL)
  1532.         {
  1533.             m_pdeHead = m_pdeHead->pdeNext;
  1534.         }
  1535.         else
  1536.         {
  1537.             pdePrev->pdeNext = pdeCur->pdeNext;
  1538.         }
  1539.  
  1540.         m_pdeSelected->pdeNext = NULL;
  1541.         if (m_pdeHead == m_pdeSelected)
  1542.             m_pdeHead = NULL;
  1543.         delete m_pdeSelected;
  1544.         m_pdeSelected = NULL;
  1545.     }
  1546.  
  1547.     return S_OK;
  1548. }
  1549.